/*
 * Collidable.h
 *
 *  Created on: 2009/01/22
 *      Author: Yongshik Cho
 */

#ifndef COLLIDABLE_H_
#define COLLIDABLE_H_

#include <vector>
#include "../core/Prerequisites.h"
#include "../core/ISmartPtr.h"
#include "../core/Vector2D.h"
#include "../core/Matrix4.h"
#include "Renderable.h"


class Collidable : public ISmartPtr<Collidable>
{
public:
	enum _COLLIDABLE_TYPE
	{
		COLLIDABLE_PIXEL,
		COLLIDABLE_LINE,
		COLLIDABLE_TRIANGLE,
		COLLIDABLE_RECT,
		COLLIDABLE_POLYGON
	};

public:
	friend class GLDevice;
	friend class Renderable;
	friend class Triangle2D;
	friend class Rect2D;
	friend class Polygon2D;
	friend class RenderObjectContainer;

	Collidable();
	Collidable(const uint8 type);
	Collidable(const String& name);
	Collidable(Collidable& rhs);
	virtual ~Collidable();

public:
	inline const String& getName() const { return mName; }
	inline void setName(const String& name) { mName = name; }

	const bool getClosed() const { return mClosed; }
	void setClosed(const bool closed) { mClosed = closed; }

	void addPoint(Vector2D p);
	void subPoint(Vector2D p);
	const bool hasPoint(Vector2D p);
	inline vector<Vector2D>& getPoints() { return mPoints; }

	const uint8 getCenterType() const { return mCenterType; }
	void setCenterType(const uint8 centerType);

	const uint8 getType() const { return mType; }

	inline const Vector2D& getPosition() { return mPosition; }
	void setPosition(const Vector2D& pos);

	inline const Vector2D& getScale() const { return mScale; }
	void setScale(const Vector2D& scale);

	inline const Vector2D& getSize() { return mSize; }
	inline void setSize(const Vector2D& size) { mSize = size; }

	inline const float getRotation() { return mRotation; }
	void setRotation(const float rotation);

	const uint32 getPointCount() const { return (uint32)mPoints.size(); }
	Vector2D* getNextPoint();
	const uint32 getLineCount();
	void* getNextLine();
	const uint32 getTriangleCount();
	void* getNextTriangle();

	virtual const Matrix4 getLocalMatrix();
	virtual const Vector2D getLocalPosition(const Vector2D& p);

	const bool in(const Vector2D& p);
	const bool in(const Collidable& rhs);
	//const bool intersects(const Line2D& rhs);
	const bool intersects(Collidable& rhs);

	inline const uint32 getPointIndex() const { return mPointIndex; }
	void setPointIndex(const uint32 index);
	inline const uint32 getLineIndex() const { return mLineIndex; }
	void setLineIndex(const uint32 index);
	inline const uint32 getTriangleIndex() const { return mTriangleIndex; }
	void setTriangleIndex(const uint32 index);

	virtual void updatePoints();

	const Collidable& operator * (const Vector2D& p)
	{
		for(uint32 i=0;i<mPoints.size();++i)
			mPoints[i] *= p;

		return *this;
	}
	const Collidable& operator *= (const Vector2D& p)
	{
		for(uint32 i=0;i<mPoints.size();++i)
			mPoints[i] *= p;

		return *this;
	}

	/** Function for writing to a stream.
	*/
	friend std::ostream& operator << ( std::ostream& o, const Collidable& c )
	{
		for(uint32 i=0;i<c.mPoints.size();++i)
			o << c.mPoints[i];

		return o;
	}

protected:
	String				mName;
	bool				mClosed;
	uint8				mType;
	vector<Vector2D>	mPoints;

	uint32				mPointIndex;
	uint32				mLineIndex;
	uint32				mTriangleIndex;

	Vector2D*			mPoint;
	void*				mLine;
	void*				mTriangle;

	Vector2D			mPosition;
	float				mRotation;
	Vector2D			mScale;
	Vector2D			mSize;

	uint8				mCenterType;
};

#endif /* COLLIDABLE_H_ */
